Categories
Vue

Developing Vue Apps with Class-Based Components — Type Annotations

Spread the love

If we prefer to use classes, we can use the class-based components API that comes with Vue.

In this article, we’ll look at how to developing Vue apps with class-based components.

TypeScript Autocomplete for External Hooks

We can add autocomplete for external hooks within our class-based components written in TypeScript.

For instance, we can write:

vue-router-hook-types.ts

import Vue from "vue";
import { Route, RawLocation } from "vue-router";

declare module "vue/types/vue" {
  interface Vue {
    beforeRouteEnter?(
      to: Route,
      from: Route,
      next: (to?: RawLocation | false | ((vm: Vue) => void)) => void
    ): void;

    beforeRouteLeave?(
      to: Route,
      from: Route,
      next: (to?: RawLocation | false | ((vm: Vue) => void)) => void
    ): void;

    beforeRouteUpdate?(
      to: Route,
      from: Route,
      next: (to?: RawLocation | false | ((vm: Vue) => void)) => void
    ): void;
  }
}

main.ts

import Vue from "vue";
import App from "./App.vue";
import Foo from "./views/Foo.vue";
import Bar from "./views/Bar.vue";
import VueRouter from "vue-router";
import "./vue-router-hook-types";
Vue.config.productionTip = false;
const routes = [
  { path: "/foo", component: Foo },
  { path: "/bar", component: Bar }
];
const router = new VueRouter({
  routes
});
Vue.use(VueRouter);
new Vue({
  router,
  render: (h) => h(App)
}).$mount("#app");

App.vue

<template>
  <div id="app">
    <router-link to="/foo">Foo</router-link>
    <router-link to="/bar">Bar</router-link>
    <router-view></router-view>
  </div>
</template>
<script>
export default {
  name: "App",
};
</script>

views/Bar.vue

<template>
  <div>bar</div>
</template>
<script>
import Vue from "vue";
import Component from "vue-class-component";
Component.registerHooks([
  "beforeRouteEnter",
  "beforeRouteLeave",
  "beforeRouteUpdate",
]);
@Component
export default class Foo extends Vue {
  beforeRouteEnter(to, from, next) {
    console.log("beforeRouteEnter");
    next();
  }
  beforeRouteUpdate(to, from, next) {
    console.log("beforeRouteUpdate");
    next();
  }
  beforeRouteLeave(to, from, next) {
    console.log("beforeRouteLeave");
    next();
  }
}
</script>

views/Foo.vue

<template>
  <div>foo</div>
</template>
<script>
import Vue from "vue";
import Component from "vue-class-component";
import "vue-class-component/hooks";

Component.registerHooks([
  "beforeRouteEnter",
  "beforeRouteLeave",
  "beforeRouteUpdate",
]);
@Component
export default class Foo extends Vue {
  beforeRouteEnter(to, from, next) {
    console.log("beforeRouteEnter");
    next();
  }
  beforeRouteUpdate(to, from, next) {
    console.log("beforeRouteUpdate");
    next();
  }
  beforeRouteLeave(to, from, next) {
    console.log("beforeRouteLeave");
    next();
  }
}
</script>

We have the vue-router-hook-types.ts with the type definitions for the Vue Router hooks.

In main.ts , we have:

import "./vue-router-hook-types";

to import the type definitions.

Then in the Foo.vue and Bar.vue components, we can see the beforeRouteEnter, beforeRouteUpdate, and beforeRouteLeave hooks in the autocomplete menu when we’re typing them into the component class code.

We can also annotate types of methods in our code.

For instance, we can write:

<template>
  <div>
    <button @click="increment">increment</button>
    <p>{{ count }}</p>
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";

@Component(({
  watch: {
    count(val: number) {
      this.log(val)
    }
  }
})
export default class HelloWorld extends Vue {
  count: number = 0

  log(val: number): void {
    console.log(val)
  }

  increment(){
    this.count++
  }
}
</script>

We have the log method that returns void and takes a val parameter with type number ,

We use that in the count watcher which is defined in the argument we pass into Component .

This way, we won’t have to worry about passing parameters with data types we don’t expect.

And the same applies to return types of methods.

Conclusion

We can annotate data types easily with TypeScript to avoid making mistakes in our Vue class-based components.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *